package iiiexamenservidor;

import basicprotocol.BasicProtocol;

import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.net.*;
import java.text.*;

public class ServerWindow extends JFrame implements Observer {

    public ServerWindow(IIIExamenServidor newServer) {
        super("Servidor (b\u00E1sico)");
        setSize(640, 480);
        setMinimumSize(new Dimension(480, 320));
        setResizable(true);
        setLocationByPlatform(true);
        setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);

        server = newServer;
        server.addObserver(this);
        addWindowListener(new WindowAdapter() {

            @Override
            public void windowClosing(WindowEvent we) {
                doQuit();
            }

        });

        setupComponents(getContentPane());
    }

    protected final void setupComponents(Container c) {

        c.setLayout(new BorderLayout());

        // Construye el sistema de menús.

        mainMenu = new JMenuBar();

        fileMenu = new JMenu("Archivo");
        quitItem = new JMenuItem("Salir");
        fileMenu.add(quitItem);
        mainMenu.add(fileMenu);

        serverMenu = new JMenu("Servidor");
        startItem = new JMenuItem("Iniciar");
        serverMenu.add(startItem);
        stopItem = new JMenuItem("Detener");
        serverMenu.add(stopItem);
        serverMenu.add(new JSeparator());
        clearItem = new JMenuItem("Borrar registro");
        serverMenu.add(clearItem);
        mainMenu.add(serverMenu);

        helpMenu = new JMenu("Ayuda");
        mainMenu.add(helpMenu);

        setJMenuBar(mainMenu);

        quitItem.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent ae) {
                doQuit();
            }

        });

        startItem.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent ae) {
                openServer();
            }

        });

        stopItem.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent ae) {
                closeServer();
            }

        });

        clearItem.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent ae) {
                doClearLog();
            }

        });

        // Construye el panel de información del servidor.

        Box bInfo = Box.createVerticalBox();

        JPanel aInfo = new JPanel();
        aInfo.setLayout(new FlowLayout(FlowLayout.LEFT));
        aInfo.setBorder(BorderFactory.createEmptyBorder(4, 4, 0, 4));
        aInfo.add(new JLabel("Direcci\u00F3n IP : "));
        aInfo.add(serverPort =
                new JFormattedTextField(new DecimalFormat("###0")));
        serverPort.addFocusListener(new FocusAdapter() {

            @Override
            public void focusLost(FocusEvent fe) {
                try {
                    int value = Integer.parseInt(serverPort.getText());
                    if (!((0 <= BasicProtocol.MIN_PORT)
                            && (value < BasicProtocol.MAX_PORT))) {
                        throw new Exception();
                    }
                } catch (Exception e) {
                    serverPort.setText(String.format(
                            "%d", server.getServerPort()));
                    showStatus(String.format(
                            "El n\u00FAmero de puerto debe ser un valor entre %d y %d",
                            BasicProtocol.MIN_PORT, BasicProtocol.MAX_PORT));
                }
            }

        });

        bInfo.add(aInfo);

        JPanel pInfo = new JPanel();

        pInfo.setBackground(getBackground());
        pInfo.setLayout(new FlowLayout(FlowLayout.LEFT));
        pInfo.setBorder(BorderFactory.createEmptyBorder(0, 4, 4, 4));
        pInfo.add(serverInfo = new JLabel());
        pInfo.add(serverStatus = new JLabel());
        bInfo.add(pInfo);

        c.add(BorderLayout.PAGE_START, bInfo);

        // Define la barra de estado.

        JPanel pStatus = new JPanel();

        pStatus.setBackground(getBackground().darker());
        pStatus.setLayout(
                new FlowLayout(FlowLayout.LEFT));
        pStatus.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
        pStatus.add(status = new JLabel());
        c.add(BorderLayout.PAGE_END, pStatus);

        // Construye el área de mensajes.

        JPanel pLog = new JPanel();

        pLog.setLayout(
                new BorderLayout());
        pLog.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
        pLog.add(BorderLayout.CENTER,
                new JScrollPane(serverLog = new JTextArea(),
                JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
                JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED));
        serverLog.setEditable(false);

        c.add(BorderLayout.CENTER, pLog);
    }

    public void init() {
        setVisible(true);
        serverPort.setPreferredSize(
                new Dimension(100, serverPort.getHeight()));
        updateServerInfo();
    }

    @Override
    public void update(Observable o, Object o1) {
        updateServerInfo();
    }

    public void doQuit() {
        if (JOptionPane.showConfirmDialog(this,
                "\u00BFDesea cerrar el servidor?",
                "Confirmar", JOptionPane.OK_CANCEL_OPTION)
                == JOptionPane.OK_OPTION) {
            server.quitServer();
        }
    }

    public void openServer() {
        try {
            int newPort = server.getServerPort();
            try {
                newPort = Integer.parseInt(serverPort.getText());
            } catch (Exception e) {
            }
            server.open(newPort);
        } catch (Exception e) {
            showStatus("No se pudo abrir el servidor..");
        }
    }

    public void closeServer() {
        try {
            server.close();
        } catch (Exception e) {
            showStatus("No se pudo cerrar el servidor..");
        }
    }

    public void updateServerInfo() {
        showServerInfo();

        startItem.setEnabled(!server.isActive());
        stopItem.setEnabled(server.isActive());
        serverPort.setEnabled(!server.isActive());
        serverPort.setEditable(!server.isActive());
        if (serverPort.isEditable()) {
            serverPort.requestFocusInWindow();
            serverPort.selectAll();
        }
    }

    public void showServerInfo() {
        serverPort.setText(String.format("%d", server.getServerPort()));
        try {
            serverInfo.setText(String.format(
                    "IP local: %s", InetAddress.getLocalHost()));
        } catch (UnknownHostException e) {
            serverInfo.setText("(host desconocido)");
        }
        serverStatus.setText(
                (server.isActive()) ? "(activo)" : "(inactivo)");
        serverStatus.setForeground(
                (server.isActive()) ? Color.GREEN.darker() : Color.RED);
    }

    public void addToLog(String msg) {
        serverLog.append(String.format("%s\n", msg));
    }

    public void doClearLog() {
        if (JOptionPane.showConfirmDialog(this,
                "\u00BFDesea borrar el registro del servidor?",
                "Confirmar", JOptionPane.OK_CANCEL_OPTION)
                == JOptionPane.OK_OPTION) {
            clearLog();
        }
    }

    public void clearLog() {
        serverLog.setText(null);
    }

    public void showStatus(String msg) {
        status.setText(msg);
    }

    public void clearStatus() {
        showStatus(null);
    }

    private IIIExamenServidor server;
    private JMenuBar mainMenu;
    private JMenu fileMenu;
    private JMenuItem quitItem;
    private JMenu serverMenu;
    private JMenuItem startItem;
    private JMenuItem stopItem;
    private JMenuItem clearItem;
    private JMenu helpMenu;
    private JFormattedTextField serverPort;
    private JLabel serverInfo;
    private JLabel serverStatus;
    private JLabel status;
    private JTextArea serverLog;
}
